<template>
  <a-modal
    width="680px"
    :visible="syncedValue"
    :ok-text="'保存'"
    cancel-text="取消"
    :mask-closable="false"
    :destroy-on-close="true"
    centered
    class="create-monitor-modal"
    @ok.stop="confirm"
    @cancel.stop="cancel"
  >
    <div slot="title">
      <a-icon type="setting" style="color: #1b4ce4;" />
      数据源配置
    </div>

    <!-- 配置信息  -->
    <div>
      <div>配置信息</div>
      <a-form-model
        ref="configInfoForm"
        :model="configInfo"
        :label-col="{ span: 4 }"
        :wrapper-col="{ span: 20 }"
      >
        <!-- 服务器 -->
        <a-form-model-item
          ref="host"
          prop="host"
          label="服务器"
          :rules="[
            {
              required: true,
              message: '请输入服务器!',
              trigger: ['blur', 'change'],
            },
          ]"
        >
          <a-input
            v-model="configInfo.host"
            :disabled="!!connectionTestLoading"
            size="small"
            placeholder="请输入服务器地址..."
            allow-clear
            @change="configInfoChange"
          />
        </a-form-model-item>
        <!-- 端口 -->
        <a-form-model-item
          ref="port"
          prop="port"
          label="端口"
          :rules="[
            {
              required: true,
              message: '请输入端口号!',
              trigger: ['blur', 'change'],
            },
          ]"
        >
          <a-input
            v-model="configInfo.port"
            :disabled="!!connectionTestLoading"
            size="small"
            placeholder="请输入端口号..."
            allow-clear
            @change="configInfoChange"
          />
        </a-form-model-item>
        <!-- 用户名 -->
        <a-form-model-item
          ref="username"
          prop="username"
          label="用户名"
          :rules="[
            {
              required: true,
              message: '请输入用户名!',
              trigger: ['blur', 'change'],
            },
          ]"
        >
          <a-input
            v-model="configInfo.username"
            :disabled="!!connectionTestLoading"
            size="small"
            placeholder="请输入用户名..."
            allow-clear
            @change="configInfoChange"
          />
        </a-form-model-item>
        <!-- 密码 -->
        <a-form-model-item
          ref="password"
          prop="password"
          label="密码"
          :rules="[
            {
              required: true,
              message: '请输入密码!',
              trigger: ['blur', 'change'],
            },
          ]"
        >
          <a-input-password
            v-model="configInfo.password"
            :disabled="!!connectionTestLoading"
            size="small"
            placeholder="请输入密码..."
            allow-clear
            @change="configInfoChange"
          />
        </a-form-model-item>
        <div class="connection-container">
          <a-space>
            <a-icon-font
              v-if="syncedConnectionResult"
              :type="iconMap[syncedConnectionResult]"
              :style="{
                color: iconColorMap[syncedConnectionResult],
              }"
            />
            <span v-if="syncedConnectionResult">
              {{ databaseConnectionResultText }}
            </span>
            <a-button
              type="primary"
              :loading="connectionTestLoading"
              size="small"
              icon="link"
              ghost
              @click="connectTest"
            >
              连接
            </a-button>
          </a-space>
        </div>
      </a-form-model>
    </div>

    <div>
      <div>数据库信息</div>
      <a-form-model
        ref="databaseForm"
        :model="databaseInfo"
        :label-col="{ span: 4 }"
        :wrapper-col="{ span: 20 }"
      >
        <!-- 选择库 -->
        <a-form-model-item
          ref="databaseName"
          prop="databaseName"
          label="选择默认库"
        >
          <a-select
            v-model="databaseInfo.databaseName"
            show-search
            option-filter-prop="children"
            :filter-option="filterOption"
            size="small"
            style="width: 100%;"
            placeholder="请选择默认库..."
            :options="databaseNameOptions"
            :disabled="!!connectionTestLoading"
            allow-clear
            @change="handleDatabaseChange"
          />
        </a-form-model-item>

        <!-- 选择模式 -->
        <a-form-model-item
          v-if="sqlType === 'POSTGRES'"
          ref="schemaName"
          prop="schemaName"
          label="选择默认模式"
        >
          <a-select
            v-model="databaseInfo.schemaName"
            show-search
            option-filter-prop="children"
            :filter-option="filterOption"
            size="small"
            style="width: 100%;"
            placeholder="请选择默认模式..."
            :options="schemaNameOptions"
            :disabled="!!connectionTestLoading"
            allow-clear
          />
        </a-form-model-item>
      </a-form-model>
    </div>
  </a-modal>
</template>

<script lang="ts">
/**
 * 数据源配置 modal
 */
import { Component, Prop, PropSync, Ref, Watch } from 'vue-property-decorator'
import {
  connectTestApi,
  getAllDatabaseApi,
  getAllSchemaApi,
} from '@/api/data-lineage'
import CancelRequestMixin from '@/components/cancel-request-mixin'
import { KV, Option } from '@/interface/interface'

@Component({
  name: 'DataSourceConfigModal',
  components: {},
  directives: {},
})
export default class DataSourceConfigModal extends CancelRequestMixin {
  @Ref('configInfoForm') readonly configInfoForm!: any
  @Ref('databaseForm') readonly databaseForm!: any
  @PropSync('value', { type: Boolean }) syncedValue!: boolean
  @PropSync('connectionResult', { type: String }) syncedConnectionResult!:
    | 'ERROR'
    | 'SUCCESS'
    | null // null - 未连接， ERROR - 连接失败，SUCCESS - 连接成功
  @Prop({
    type: Object,
    default: () => {
      return {}
    },
  })
  config!: any
  @Prop({ type: String, default: 'MYSQL' }) sqlType!: string
  // configInfo 配置信息
  private configInfo: any = {
    host: undefined,
    port: undefined,
    username: undefined,
    password: undefined,
  }
  // 数据库信息
  private databaseInfo: any = {
    databaseName: undefined,
    schemaName: undefined,
  }
  private connectionTestLoading: boolean | { delay: 500 } = false // loading
  databaseConnectionResultText: string = ''
  iconMap: KV<string> = {
    SUCCESS: 'icon-chenggong',
    ERROR: 'icon-shibai',
  }
  iconColorMap: KV<string> = {
    SUCCESS: '#78C06E',
    ERROR: '#E6505A',
  }

  // 库 options
  private databaseNameOptions: Array<Option> = []

  public filterOption(input: any, option: any) {
    return option.componentOptions.children[0].text
      .toLowerCase()
      .includes(input.toLowerCase())
  }

  // 模式 options
  private schemaNameOptions: Array<Option> = []

  @Watch('syncedValue')
  public visibleChange(value: boolean) {
    if (value) {
      const {
        host,
        port,
        username,
        password,
        databaseName,
        schemaName,
      } = this.config
      this.configInfo = {
        host,
        port,
        username,
        password,
      }
      this.databaseInfo = {
        databaseName,
        schemaName,
      }
    }
  }

  /**
   * 配置信息更改
   */
  private configInfoChange() {
    this.syncedConnectionResult = null
    this.databaseInfo.databaseName = undefined
    this.databaseInfo.schemaName = undefined
    this.databaseNameOptions = []
    this.schemaNameOptions = []
  }

  /**
   * 测试连接服务器
   */
  public async connectTest() {
    this.configInfoForm.validate(async (success: boolean, errors: any) => {
      if (success) {
        try {
          const parameters: any = {
            sqlType: this.sqlType,
            ...this.configInfo,
          }
          const source: any = this.createCancelTokenSources('CONNECT_TEST')
          this.connectionTestLoading = { delay: 500 }
          const response: any = await connectTestApi({
            data: parameters,
            cancelToken: source.token,
          })
          const { code, message } = response.data
          if (code === 200) {
            this.syncedConnectionResult = 'SUCCESS'
            this.databaseConnectionResultText = message || '连接成功'
            this.getAllDatabase()
          } else {
            this.clearDatabaseInfo()
            this.syncedConnectionResult = 'ERROR'
            this.databaseConnectionResultText = message || '连接失败'
          }
        } catch (error) {
          this.clearDatabaseInfo()
          console.error(error)
        } finally {
          this.connectionTestLoading = false
        }
      } else {
        this.clearDatabaseInfo()
        console.error(errors)
      }
    })
  }

  /**
   * 获取数据库
   * @private
   */
  private async getAllDatabase() {
    try {
      const parameters: any = {
        sqlType: this.sqlType,
        ...this.configInfo,
      }
      const source: any = this.createCancelTokenSources('GET_ALL_DATABASE')
      const response: any = await getAllDatabaseApi({
        data: parameters,
        cancelToken: source.token,
      })
      const { data, code, message } = response.data
      if (code === 200) {
        this.databaseNameOptions = data.map((item: any) => {
          return { label: item, value: item }
        })
        if (!data || !data.includes(this.configInfo.databaseName)) {
          this.configInfo.databaseName = undefined
        }
        if (this.configInfo.databaseName) {
          this.getAllSchema()
        }
      } else {
        this.clearDatabaseInfo()
        this.$message.error(message || '未知错误！')
      }
    } catch (error) {
      console.error(error)
    } finally {
      this.connectionTestLoading = false
    }
  }

  private handleDatabaseChange() {
    if (this.sqlType === 'POSTGRES') {
      this.getAllSchema()
    }
  }

  /**
   * 获取数据模式
   * @private
   */
  private async getAllSchema() {
    try {
      const parameters: any = {
        databaseName: this.databaseInfo.databaseName,
        sqlType: this.sqlType,
        ...this.configInfo,
      }
      const source: any = this.createCancelTokenSources('GET_ALL_SCHEMA')
      const response: any = await getAllSchemaApi({
        data: parameters,
        cancelToken: source.token,
      })
      const { data, code, message } = response.data
      if (code === 200) {
        if (!data) {
          return
        }
        this.schemaNameOptions = data.map((item: any) => {
          return { label: item, value: item }
        })
        if (!data || !data.includes(this.configInfo.schemaName)) {
          this.configInfo.schemaName = undefined
        }
      } else {
        this.clearDatabaseInfo()
        this.$message.error(message || '未知错误！')
      }
    } catch (error) {
      console.error(error)
    } finally {
      this.connectionTestLoading = false
    }
  }

  private clearDatabaseInfo() {
    this.configInfo.databaseName = undefined
    this.configInfo.schemaName = undefined
    this.databaseNameOptions = []
    this.schemaNameOptions = []
  }

  public confirm() {
    if (this.connectionTestLoading) {
      this.$message.warning('正在连接！')
      return
    }
    // let validateResult: boolean = true
    // this.configInfoForm.validate(async (success: boolean, errors: any) => {
    //   if (!success) {
    //     validateResult = false
    //     console.error('error:', errors)
    //   }
    // })
    // this.databaseForm.validate(async (success: boolean, errors: any) => {
    //   if (!success) {
    //     validateResult = false
    //     console.error('error:', errors)
    //   }
    // })
    // if (validateResult) {
    this.$emit('confirm', { ...this.configInfo, ...this.databaseInfo })
    this.syncedValue = false
    // }
  }

  public cancel() {
    if (this.connectionTestLoading) {
      this.$message.warning('正在连接！')
      return
    }
    this.syncedValue = false
  }
}
</script>

<style lang="less" scoped>
.create-monitor-modal {
  :deep(.ant-form-item) {
    margin-bottom: 6px;
  }

  .connection-container {
    align-items: center;
    display: flex;
    justify-content: right;
  }
}
</style>
